/*
* This file is a part of the open-eBackup project.
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
* If a copy of the MPL was not distributed with this file, You can obtain one at
* http://mozilla.org/MPL/2.0/.
*
* Copyright (c) [2024] Huawei Technologies Co.,Ltd.
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
*/
#include "gtest/gtest.h"
#include "PluginUtilities.h"
#include "named_stub.h"
#include "mockcpp/mockcpp.hpp"
#include "common/CTime.h"
#include "system/System.hpp"

using namespace std;

class PluginUtilitiesTest : public testing::Test {
public:
    void SetUp();
    void TearDown();
    static void SetUpTestCase();
    static void TearDownTestCase();
    LLTSTUB::Stub stub;
    const uint64_t NUM_1024 = 1024;
    const uint64_t NUM_2 = 2;
    const uint64_t KB_size = NUM_1024;
    const uint64_t MB_size = NUM_1024 * KB_size;
    const uint64_t GB_size = NUM_1024 * MB_size;
    const uint64_t TB_size = NUM_1024 * GB_size;
    const uint64_t PB_size = NUM_1024 * TB_size;
    const uint16_t MP_FAILED = Module::FAILED;
    const uint16_t MP_SUCCESS = Module::SUCCESS;
};

static int StubFunctionSucc()
{
    return 0;
}

void PluginUtilitiesTest::SetUp()
{
    MOCKER_CPP(&sleep)
            .stubs()
            .will(invoke(StubFunctionSucc));
}

void PluginUtilitiesTest::TearDown()
{
    GlobalMockObject::verify(); // 校验mock规范并清除mock规范
}
void PluginUtilitiesTest::SetUpTestCase() {}
void PluginUtilitiesTest::TearDownTestCase() {}

static int MkdirSuccess(const char* path, int mode)
{
    return Module::SUCCESS;
}

static int MkdirFail(const char* path, int mode)
{
    return Module::FAILED;
}

/*
 * 用例名称:CheckDeviceNetworkConnect
 * 前置条件：无
 * check点：输入是ip列表，以逗号分割，检查通过管理网络访问8088端口是否连通
 */
TEST_F(PluginUtilitiesTest, CheckDeviceNetworkConnect)
{
    MOCKER_CPP(&Module::runShellCmdWithOutput)
            .stubs()
            .will(returnValue(MP_FAILED));

    string str = "xxx";
    bool ret = OBSPlugin::CheckDeviceNetworkConnect(str);
    EXPECT_EQ(ret, false);
}

/*
 * 用例名称:FormatTimeToStr
 * 前置条件：无
 * check点：时间转字符串，转换结果形式为%Y-%m-%d-%H:%M:%S
 */
TEST_F(PluginUtilitiesTest, FormatTimeToStr)
{
    time_t timeInSeconds = 1577257503;
    string res = "2019-12-25-15:05:03";

    string ret = OBSPlugin::FormatTimeToStr(timeInSeconds);

    EXPECT_EQ(ret, res);
}

/*
 * 用例名称:LogCmdExecuteError
 * 前置条件：无
 * check点：打印error
 */
TEST_F(PluginUtilitiesTest, LogCmdExecuteError)
{
    int ret;
    std::vector<std::string> output;
    std::vector<std::string> errOutput;
    output.emplace_back("sucess");
    errOutput.emplace_back("no error");

    EXPECT_NO_THROW(OBSPlugin::LogCmdExecuteError(ret, output, errOutput));
}

/*
 * 用例名称:RunShellCmd
 * 前置条件：无
 * check点：执行cmd命令
 */
TEST_F(PluginUtilitiesTest, RunShellCmd1)
{
    MOCKER_CPP(&Module::runShellCmdWithOutput)
            .stubs()
            .will(returnValue(MP_FAILED));
    std::string cmd = "cmd";
    std::vector<std::string> paramList;
    paramList.emplace_back("failed");

    int ret = OBSPlugin::RunShellCmd(cmd, paramList);
    EXPECT_EQ(ret, MP_FAILED);
}

TEST_F(PluginUtilitiesTest, RunShellCmd2)
{
    MOCKER_CPP(&Module::runShellCmdWithOutput)
            .stubs()
            .will(returnValue(MP_SUCCESS));
    std::string cmd = "cmd";
    std::vector<std::string> paramList;
    paramList.emplace_back("failed");

    int ret = OBSPlugin::RunShellCmd(cmd, paramList);
    EXPECT_EQ(ret, MP_SUCCESS);
}

/*
 * 用例名称:RunShellCmd
 * 前置条件：无
 * check点：执行cmd命令with output
 */
TEST_F(PluginUtilitiesTest, RunShellCmdWithOutput1)
{
    MOCKER_CPP(&Module::runShellCmdWithOutput)
        .stubs()
        .will(returnValue(MP_FAILED));
    std::string cmd = "cmd";
    std::vector<std::string> paramList;
    std::vector<std::string> output;
    paramList.emplace_back("sucess");

    int ret = OBSPlugin::RunShellCmd(cmd, paramList, output);
    EXPECT_EQ(ret, MP_FAILED);
}

TEST_F(PluginUtilitiesTest, RunShellCmdWithOutput2)
{
    MOCKER_CPP(&Module::runShellCmdWithOutput)
        .stubs()
        .will(returnValue(MP_SUCCESS));
    std::string cmd = "cmd";
    std::vector<std::string> paramList;
    std::vector<std::string> output;
    paramList.emplace_back("sucess");

    int ret = OBSPlugin::RunShellCmd(cmd, paramList, output);
    EXPECT_EQ(ret, MP_SUCCESS);
}


/*
 * 用例名称:GenerateHash
 * 前置条件：无
 * check点：获得hash值
 */
TEST_F(PluginUtilitiesTest, GenerateHash)
{
    size_t ret = OBSPlugin::GenerateHash("55");
    EXPECT_EQ(ret, ret);
}

/*
 * 用例名称:GetCurrentTimeInSeconds
 * 前置条件：无
 * check点：获得当前时间点距离1970.01.01 00：00：00的秒数量
 */
TEST_F(PluginUtilitiesTest, GetCurrentTimeInSeconds)
{
    time_t currTime;
    time_t ret = OBSPlugin::GetCurrentTimeInSeconds();
    Module::CTime::Now(currTime);

    EXPECT_EQ(ret, currTime);
}

/*
 * 用例名称:GetCurrentTimeInSecondsWithParam
 * 前置条件：无
 * check点：获得当前时间点距离1970.01.01 00：00：00的秒数量
 */
TEST_F(PluginUtilitiesTest, GetCurrentTimeInSecondsWithParam)
{
    time_t currTime;
    string dateAndTimeString;
    time_t ret = OBSPlugin::GetCurrentTimeInSecondsString(dateAndTimeString);
    Module::CTime::Now(currTime);

    EXPECT_EQ(ret, currTime);
}

/*
 * 用例名称：WriteFile
 * 前置条件：无
 * check点：保存备份统计信息
 **/
TEST_F(PluginUtilitiesTest, WriteFile)
{
    string path = "/home/statistic.json";
    std::vector<std::string> statisticInfo;
    statisticInfo.emplace_back("test");
    bool ret = OBSPlugin::WriteFile(path, statisticInfo);
    EXPECT_EQ(ret, true);
}

/*
 * 用例名称：ReadFile
 * 前置条件：无
 * check点：获取备份统计信息
 **/
TEST_F(PluginUtilitiesTest, ReadFile)
{
    string path = "/home/statistic.json";
    std::vector<std::string> statisticInfo;
    bool ret = OBSPlugin::ReadFile(path, statisticInfo);
    EXPECT_EQ(ret, true);
    string path1 = "/home1/statistic.json";
    ret = OBSPlugin::ReadFile(path1, statisticInfo);
    EXPECT_EQ(ret, false);
}

/*
 * 用例名称:CreateDirectory
 * 前置条件：无
 * check点：创建目录，可多层
 */
TEST_F(PluginUtilitiesTest, CreateDirectory1)
{
    stub.set(mkdir, MkdirSuccess);
    string path;
    bool ret = OBSPlugin::CreateDirectory(path);
    EXPECT_EQ(ret, true);
    stub.reset(mkdir);
}

TEST_F(PluginUtilitiesTest, CreateDirectory2)
{
    stub.set(mkdir, MkdirSuccess);
    string path = "/makepathNotExists";
    MOCKER_CPP(&OBSPlugin::IsDirExist)
        .stubs()
        .will(returnValue(true))
        .then(returnValue(false));
    bool ret = OBSPlugin::CreateDirectory(path);
    EXPECT_EQ(ret, true);
    stub.reset(mkdir);
}

TEST_F(PluginUtilitiesTest, CreateDirectory3)
{
    stub.set(mkdir, MkdirFail);
    string path = "/makepathNotExists";
    MOCKER_CPP(&OBSPlugin::IsDirExist)
        .stubs()
        .will(returnValue(true))
        .then(returnValue(false));
    bool ret = OBSPlugin::CreateDirectory(path);
    EXPECT_EQ(ret, true);
    stub.reset(mkdir);
}

/*
 * 用例名称:测试递归生成目录success
 * 前置条件：多级目录
 * check点：生成目录成功，跳过已存在
 */
TEST_F(PluginUtilitiesTest, RecurseCreateDirectory)
{
    stub.set(mkdir, MkdirSuccess);
    std::string path = "/tmp/llt/RecurseCreateDirectoryTest";
    bool ret = OBSPlugin::RecurseCreateDirectory(path);
    EXPECT_EQ(ret, true);
    stub.reset(mkdir);
}

/*
 * 用例名称:Remove
 * 前置条件：无
 * check点：删除目录
 */
TEST_F(PluginUtilitiesTest, Remove1)
{
    string path = "/dddd";
    EXPECT_TRUE(OBSPlugin::Remove(path));
}

TEST_F(PluginUtilitiesTest, Remove2)
{
    string str = "err";
    boost::filesystem::path path1 = "/a/b.txt";
    boost::filesystem::path path2 = "/a/b.txt";
    boost::system::error_code ec;
    MOCKER_CPP(boost::filesystem::exists, bool(const boost::filesystem::path&))
            .stubs()
            .will(throws(boost::filesystem::filesystem_error(str, path1, path2, ec)));

    string path = "/dddd";
    EXPECT_FALSE(OBSPlugin::Remove(path));
}

TEST_F(PluginUtilitiesTest, Remove3)
{
    string str = "err";
    boost::filesystem::path path1 = "/a/b.txt";
    boost::filesystem::path path2 = "/a/b.txt";
    boost::system::error_code ec;
    MOCKER_CPP(boost::filesystem::exists, bool(const boost::filesystem::path&))
            .stubs()
            .will(returnValue(true));
    MOCKER_CPP(boost::filesystem::remove_all, boost::uintmax_t(const boost::filesystem::path&))
            .stubs()
            .will(throws(boost::filesystem::filesystem_error(str, path1, path2, ec)));

    string path = "/dddd";
    EXPECT_FALSE(OBSPlugin::Remove(path));
}

/*
 * 用例名称:IsPathExists
 * 前置条件：无
 * check点：文件是否存在
 */
TEST_F(PluginUtilitiesTest, IsPathExists_FALSE)
{
    string path = "/pathNotExists";
    bool ret = OBSPlugin::IsPathExists(path);
    EXPECT_FALSE(OBSPlugin::IsPathExists(path));
}

/*
 * 用例名称:IsPathExists
 * 前置条件：无
 * check点：文件是否存在
 */
TEST_F(PluginUtilitiesTest, IsPathExists_TRUE)
{
    string path = "/";
    EXPECT_TRUE(OBSPlugin::IsPathExists(path));
}

/*
 * 用例名称:IsPathExists
 * 前置条件：无
 * check点：文件是否存在
 */
TEST_F(PluginUtilitiesTest, IsPathExists)
{
    string str = "err";
    boost::filesystem::path path1 = "/a/b.txt";
    boost::filesystem::path path2 = "/a/b.txt";
    boost::system::error_code ec;
    MOCKER_CPP(boost::filesystem::exists, bool(const boost::filesystem::path&))
            .stubs()
            .will(throws(boost::filesystem::filesystem_error(str, path1, path2, ec)));

    string path = "/";
    EXPECT_FALSE(OBSPlugin::IsPathExists(path));
}

/*
 * 用例名称:Rename源目录不存在
 * 前置条件：无
 * check点：文件重命名或实现文件移动
 */
TEST_F(PluginUtilitiesTest, Rename1)
{
    string str1 = "/aaaaa";
    string str2 = "/bbbbb";
    EXPECT_FALSE(OBSPlugin::Rename(str1, str2));
}

TEST_F(PluginUtilitiesTest, Rename2)
{
    string str1 = "/tmp/llt/RecurseCreateDirectoryTest";
    string str2 = "/tmp/llt/RecurseCreateDirectoryTest";
    EXPECT_FALSE(OBSPlugin::Rename(str1, str2));
}

TEST_F(PluginUtilitiesTest, Rename3)
{
    string str1 = "/tmp/llt/RecurseCreateDirectoryTest";
    string str2 = "/tmp/llt/RecurseCreateDirectoryTest";
    MOCKER_CPP(OBSPlugin::IsPathExists)
            .stubs()
            .will(returnValue(true));
    MOCKER_CPP(OBSPlugin::Remove)
            .stubs()
            .will(returnValue(false));
    EXPECT_FALSE(OBSPlugin::Rename(str1, str2));
}

TEST_F(PluginUtilitiesTest, Rename4)
{
    string str1 = "/tmp/llt/RecurseCreateDirectoryTest";
    string str2 = "/tmp/llt/RecurseCreateDirectoryTest";
    MOCKER_CPP(rename)
            .stubs()
            .will(returnValue(0));
    EXPECT_FALSE(OBSPlugin::Rename(str1, str2));
}

/*
 * 用例名称:获取路径名返回null
 * 前置条件：无
 * check点：文件重命名或实现文件移动
 */
TEST_F(PluginUtilitiesTest, GetPathName_NLL)
{
    string path = "path";

    std::string ret = OBSPlugin::GetPathName(path);
    EXPECT_EQ(ret, "");
}
/*
 * 用例名称:获取路径名
 * 前置条件：无
 * check点：文件重命名或实现文件移动
 */
TEST_F(PluginUtilitiesTest, GetPathName_Success)
{
    string path = "aaa/aa.txt";

    std::string ret = OBSPlugin::GetPathName(path);
    EXPECT_EQ(ret, "aaa");
}

/*
 * 用例名称:GetFileName
 * 前置条件：无
 * check点：根据文件路径获取文件名字
 */
TEST_F(PluginUtilitiesTest, GetFileName)
{
    string filePath = "/xxx/yyy/file.cpp";
    string fileName = "file.cpp";
    string ret = OBSPlugin::GetFileName(filePath);

    EXPECT_EQ(ret, fileName);
}

/*
 * 用例名称:GetFileName未找到分隔符
 * 前置条件：无
 * check点：根据文件路径获取文件名字
 */
TEST_F(PluginUtilitiesTest, GetFileName1)
{
    string filePath = "test";
    string fileName = "file.cpp";
    string ret = OBSPlugin::GetFileName(filePath);

    EXPECT_EQ(ret, filePath);
}

/*
 * 用例名称：IsDirExist
 * 前置条件：无
 * check点：文件夹是否存在
 **/
TEST_F(PluginUtilitiesTest, IsDirExist)
{
    string str = "err";
    boost::filesystem::path path1 = "/a/b.txt";
    boost::filesystem::path path2 = "/a/b.txt";
    boost::system::error_code ec;
    MOCKER_CPP(boost::filesystem::is_directory, bool(const boost::filesystem::path&))
            .stubs()
            .will(throws(boost::filesystem::filesystem_error(str, path1, path2, ec)));
    std::string dstDir = "/";
    bool ret = OBSPlugin::IsDirExist(dstDir);
    EXPECT_EQ(ret, false);
}

/*
 * 用例名称：IsDirExist路径不存在
 * 前置条件：无
 * check点：文件夹是否存在
 **/
TEST_F(PluginUtilitiesTest, IsDirExist1)
{
    std::string dstDir = "/aaaaa/bbb.txt";
    bool ret = OBSPlugin::IsDirExist(dstDir);
    EXPECT_EQ(ret, false);
}

/*
 * 用例名称：IsFileExist路径不存在
 * 前置条件：无
 * check点：文件夹是否存在
 **/
TEST_F(PluginUtilitiesTest, IsFileExist1)
{
    std::string faileName = "/aaaaa/bbbb.txt";
    bool ret = OBSPlugin::IsFileExist(faileName);
    EXPECT_EQ(ret, false);
}

TEST_F(PluginUtilitiesTest, IsFileExist2)
{
    std::string faileName = "/usr/bin/vi";
    bool ret = OBSPlugin::IsFileExist(faileName);
    EXPECT_EQ(ret, true);
}

TEST_F(PluginUtilitiesTest, IsFileExist3)
{
    std::string faileName = "/usr/bin/vi";
    string str = "err";
    boost::filesystem::path path1 = "/a/b.txt";
    boost::filesystem::path path2 = "/a/b.txt";
    boost::system::error_code ec;
    MOCKER_CPP(boost::filesystem::is_regular_file, bool(const boost::filesystem::path&))
            .stubs()
            .will(throws(boost::filesystem::filesystem_error(str, path1, path2, ec)));
    bool ret = OBSPlugin::IsFileExist(faileName);
    EXPECT_EQ(ret, false);
}

/*
 * 用例名称:FormatCapacity
 * 前置条件：无
 * check点：格式化存储容量
 */

TEST_F(PluginUtilitiesTest, FormatCapacity_B)
{
    uint64_t capacity = 512;
    string ret = OBSPlugin::FormatCapacity(capacity);

    string res = "512 B";
    EXPECT_EQ(ret, res);
}

TEST_F(PluginUtilitiesTest, FormatCapacity_KB)
{
    uint64_t capacity = PluginUtilitiesTest::KB_size *2;
    string ret = OBSPlugin::FormatCapacity(capacity);

    string res = "2.0 KB";
    EXPECT_EQ(ret, res);
}

TEST_F(PluginUtilitiesTest, FormatCapacity_MB)
{
    uint64_t capacity = PluginUtilitiesTest::MB_size *2;
    string ret = OBSPlugin::FormatCapacity(capacity);

    string res = "2.0 MB";
    EXPECT_EQ(ret, res);
}

TEST_F(PluginUtilitiesTest, FormatCapacity_GB)
{
    uint64_t capacity = PluginUtilitiesTest::GB_size *2;
    string ret = OBSPlugin::FormatCapacity(capacity);

    string res = "2.0 GB";
    EXPECT_EQ(ret, res);
}

TEST_F(PluginUtilitiesTest, FormatCapacity_TB)
{
    uint64_t capacity = PluginUtilitiesTest::TB_size *2;
    string ret = OBSPlugin::FormatCapacity(capacity);

    string res = "2.00 TB";
    EXPECT_EQ(ret, res);
}

TEST_F(PluginUtilitiesTest, FormatCapacity_PB)
{
    uint64_t capacity = PluginUtilitiesTest::PB_size *2;
    string ret = OBSPlugin::FormatCapacity(capacity);

    string res = "2.0 PB";
    EXPECT_EQ(ret, res);
}

/*
 * 用例名称:RemoveFile
 * 前置条件：无
 * check点：删除文件
 */
TEST_F(PluginUtilitiesTest, RemoveFile)
{
    string filePath = "/xxx/yyy/file.cpp";
    bool ret = OBSPlugin::RemoveFile(filePath);

    EXPECT_EQ(ret, true);
}

TEST_F(PluginUtilitiesTest, RemoveFile1)
{
    string filePath = "/aaa/";
    bool ret = OBSPlugin::RemoveFile(filePath);

    EXPECT_EQ(ret, true);
}

TEST_F(PluginUtilitiesTest, RemoveFile2)
{
    string filePath = "/aaa/";
    string str = "err";
    boost::filesystem::path path1 = "/a/b.txt";
    boost::filesystem::path path2 = "/a/b.txt";
    boost::system::error_code ec;
    MOCKER_CPP(boost::filesystem::is_regular_file, bool(const boost::filesystem::path&))
            .stubs()
            .will(throws(boost::filesystem::filesystem_error(str, path1, path2, ec)));

    bool ret = OBSPlugin::RemoveFile(filePath);

    EXPECT_EQ(ret, false);
}

TEST_F(PluginUtilitiesTest, RemoveFile3)
{
    string filePath = "/aaa/";
    MOCKER_CPP(boost::filesystem::is_regular_file, bool(const boost::filesystem::path&))
            .stubs()
            .will(returnValue(true));
    MOCKER_CPP(boost::filesystem::remove, bool(const boost::filesystem::path&))
            .stubs()
            .will(returnValue(true));
    bool ret = OBSPlugin::RemoveFile(filePath);

    EXPECT_EQ(ret, true);
}

TEST_F(PluginUtilitiesTest, RemoveFile4)
{
    string filePath = "/aaa/";
    MOCKER_CPP(boost::filesystem::is_regular_file, bool(const boost::filesystem::path&))
            .stubs()
            .will(returnValue(true));
    MOCKER_CPP(boost::filesystem::remove, bool(const boost::filesystem::path&))
            .stubs()
            .will(returnValue(false));
    bool ret = OBSPlugin::RemoveFile(filePath);

    EXPECT_EQ(ret, false);
}

/*
 * 用例名称:CopyFile
 * 前置条件：无
 * check点：拷贝文件
 */

TEST_F(PluginUtilitiesTest, CopyFile)
{
    MOCKER_CPP(&OBSPlugin::IsFileExist)
            .stubs()
            .will(returnValue(false))
            .then(returnValue(true));

    string srcfile = "/";
    string dstfile = "/xxx/yyy/file.cpp";

    bool ret = OBSPlugin::CopyFile(srcfile, dstfile);
    EXPECT_EQ(ret, false);
    ret = OBSPlugin::CopyFile(srcfile, dstfile);
    EXPECT_EQ(ret, false);
}

/*
 * 用例名称:GetFileListInDirectory
 * 前置条件：无
 * check点：获得某路径下文件列表
 */
TEST_F(PluginUtilitiesTest, GetFileListInDirectory1)
{
    string dir = "/xxx/yyy";
    vector<string> fileList;
    bool ret = OBSPlugin::GetFileListInDirectory(dir, fileList);

    EXPECT_EQ(ret, false);
}

TEST_F(PluginUtilitiesTest, GetFileListInDirectory2)
{
    string dir = "/";
    vector<string> fileList;
    bool ret = OBSPlugin::GetFileListInDirectory(dir, fileList);

    EXPECT_EQ(ret, true);
}

TEST_F(PluginUtilitiesTest, GetFileListInDirectory3)
{
    string dir = "/";
    vector<string> fileList;
    string str = "err";
    boost::filesystem::path path1 = "/a/b.txt";
    boost::filesystem::path path2 = "/a/b.txt";
    boost::system::error_code ec;
    MOCKER_CPP(boost::filesystem::exists, bool(const boost::filesystem::path&))
            .stubs()
            .will(throws(boost::filesystem::filesystem_error(str, path1, path2, ec)));

    bool ret = OBSPlugin::GetFileListInDirectory(dir, fileList);
    EXPECT_EQ(ret, false);
}

/*
 * 用例名称:GetDirListInDirectory
 * 前置条件：无
 * check点：获得某路径下文件列表
 */
TEST_F(PluginUtilitiesTest, GetDirListInDirectory)
{
    string dir = "/xxx/yyy";
    vector<string> fileList;
    bool ret = OBSPlugin::GetDirListInDirectory(dir, fileList);

    EXPECT_EQ(ret, false);
}

TEST_F(PluginUtilitiesTest, GetDirListInDirectory2)
{
    string dir = "/";
    vector<string> fileList;
    bool ret = OBSPlugin::GetDirListInDirectory(dir, fileList);

    EXPECT_EQ(ret, true);
}

TEST_F(PluginUtilitiesTest, GetDirListInDirectory3)
{
    string dir = "/";
    vector<string> fileList;
    string str = "err";
    boost::filesystem::path path1 = "/a/b.txt";
    boost::filesystem::path path2 = "/a/b.txt";
    boost::system::error_code ec;
    MOCKER_CPP(boost::filesystem::exists, bool(const boost::filesystem::path&))
            .stubs()
            .will(throws(boost::filesystem::filesystem_error(str, path1, path2, ec)));

    bool ret = OBSPlugin::GetDirListInDirectory(dir, fileList);
    EXPECT_EQ(ret, false);
}

/*
 * 用例名称:GetParentDirName
 * 前置条件：无
 * check点：获得父目录名
 */
TEST_F(PluginUtilitiesTest, GetParentDirName)
{
    string dir = "";
    std::string ret = OBSPlugin::GetParentDirName(dir);

    EXPECT_EQ(ret, "");
}

TEST_F(PluginUtilitiesTest, GetParentDirName_2)
{
    string dir = "/aaa/bbb/";
    std::string ret = OBSPlugin::GetParentDirName(dir);

    EXPECT_EQ(ret, "bbb");
}

/*
 * 用例名称:FloatToString
 * 前置条件：无
 * check点：浮点数转为字符
 */
TEST_F(PluginUtilitiesTest, FloatToString)
{
    std::string ret = OBSPlugin::FloatToString(1.23, 1);

    EXPECT_EQ(ret, "1.2");
}

/*
 * 用例名称:StripWhiteSpace
 * 前置条件：无
 * check点：去除\n
 */
TEST_F(PluginUtilitiesTest, StripWhiteSpace)
{
    std::string str = "asd\naa";

    EXPECT_NO_THROW(OBSPlugin::StripWhiteSpace(str));
}

/*
 * 用例名称:ReverseSlash
 * 前置条件：无
 * check点：ReverseSlash
 */
TEST_F(PluginUtilitiesTest, ReverseSlash)
{
    std::string ret = OBSPlugin::ReverseSlash("aaa");
    EXPECT_EQ(ret, "aaa");
}

/*
 * 用例名称:PathJoin
 * 前置条件：无
 * check点：组装路径
 */
TEST_F(PluginUtilitiesTest, PathJoin)
{
    std::string ret = OBSPlugin::PathJoin("aaa", "bbb");
    EXPECT_EQ(ret, "aaa/bbb");
}

TEST_F(PluginUtilitiesTest, PathJoin2)
{
    std::string ret = OBSPlugin::PathJoin();
    EXPECT_EQ(ret, "");
}

/*
 * 用例名称:LowerCase
 * 前置条件：无
 * check点：将字符转为小写
 */
TEST_F(PluginUtilitiesTest, LowerCase)
{
    std::string str = "AbC";

    std::string ret = OBSPlugin::LowerCase(str);
    EXPECT_EQ(ret, "abc");
}

/*
 * 用例名称:测试递归生成目录
 * 前置条件：多级目录
 * check点：生成目录成功，跳过已存在
 */
TEST_F(PluginUtilitiesTest, FormatSpeed)
{
    uint64_t speed = MB_size * NUM_2;
    std::string ret = OBSPlugin::FormatSpeed(speed);
    EXPECT_EQ(ret, "2.0MBps");

    speed = GB_size * NUM_2;
    ret = OBSPlugin::FormatSpeed(speed);
    EXPECT_EQ(ret, "2.0GBps");

    speed = TB_size * NUM_2;
    ret = OBSPlugin::FormatSpeed(speed);
    EXPECT_EQ(ret, "2.0TBps");

    speed = KB_size * NUM_2;
    ret = OBSPlugin::FormatSpeed(speed);
    EXPECT_EQ(ret, "2.0KBps");

    speed = PB_size * NUM_2;
    ret = OBSPlugin::FormatSpeed(speed);
    EXPECT_EQ(ret, "2.0PBps");

    speed = 1;
    ret = OBSPlugin::FormatSpeed(speed);
    EXPECT_EQ(ret, "1Bytes/s");
}

/*
 * 用例名称：GetRealPath
 * 前置条件：无
 * check点：获取真实路径
 **/
TEST_F(PluginUtilitiesTest, GetRealPath)
{
    std::string path = "/home/../home";
    std::string realPath = OBSPlugin::GetRealPath(path);
    EXPECT_EQ(realPath, "/home");
    path = "/abcdefg";
    realPath = OBSPlugin::GetRealPath(path);
    EXPECT_EQ(realPath, "");
}

/*
 * 用例名称：GetDirName
 * 前置条件：无
 * check点：获取目录名称
 **/
TEST_F(PluginUtilitiesTest, GetDirName)
{
    std::string dir = "/home/test.txt";
    std::string dirName = OBSPlugin::GetDirName(dir);
    EXPECT_EQ(dirName, "/home");
}

/*
 * 用例名称：IsDir
 * 前置条件：无
 * check点：判断路径是否为目录
 **/
TEST_F(PluginUtilitiesTest, IsDir)
{
    std::string dir = "/home";
    bool ret = OBSPlugin::IsDir(dir);
    EXPECT_EQ(ret, true);
}

TEST_F(PluginUtilitiesTest, testPrepareUnZipCommand)
{
    string workDir = "/home";
    string dirMetaPath = "filemeta";
    string tarCmd = "tar -I pigz -xf ";
    string cCmd = " -C . &&";
    string dirCacheZipFileName = dirMetaPath + "/metafile_DIRCACHE.gz";
    string fCacheZipFileName = dirMetaPath + "/metafile_FILECACHE.gz";
    string metaZipFilename  = dirMetaPath + "/metafile_META.gz";
    string xmetaZipFileName = dirMetaPath + "/metafile_XMETA.gz";
    string execCmd = "cd " + workDir + ";" + tarCmd + dirCacheZipFileName + cCmd + tarCmd + fCacheZipFileName + cCmd
        + tarCmd + metaZipFilename + cCmd + tarCmd + xmetaZipFileName + " -C . ";
    EXPECT_EQ(OBSPlugin::PrepareUnZipCommand(workDir, dirCacheZipFileName, fCacheZipFileName, metaZipFilename,
        xmetaZipFileName), execCmd);
}

TEST_F(PluginUtilitiesTest, testCheckUnzipMetafileFailed)
{
    string execCmd = "ls";
    string workDir = "/home";

    EXPECT_EQ(OBSPlugin::CheckUnzipMetafileSucceed(execCmd, workDir), false);
}

TEST_F(PluginUtilitiesTest, testCheckMetafileExistsFailed)
{
    string workDir = "/home";
    EXPECT_EQ(OBSPlugin::CheckMetafileExists(workDir), false);
}

TEST_F(PluginUtilitiesTest, testStandardPath)
{
    string path = "/MetaFS//cache";
    EXPECT_EQ(OBSPlugin::StandardPath(path), "/MetaFS/cache");
}


TEST_F(PluginUtilitiesTest, testCheckAndDeleteFiles)
{
    string path = "/home/filename.txt";
    string execCmd = "cd /home; touch filename.txt;";
    vector<string> output;
    vector<string> errOutput;
    int retryCnt = 0;
    do {
        int ret = Module::runShellCmdWithOutput(INFO, "ObsTest", 0, execCmd, {}, output, errOutput);
        if (ret != 0) {
            sleep(1);
            continue;
        }
    } while (++retryCnt <= 4);

    EXPECT_NO_THROW(OBSPlugin::CheckAndDeleteFiles(path));
}

TEST_F(PluginUtilitiesTest, CheckIsValidIPv6)
{
    std::string test1 = "192.168.1.1";
    std::string test2 = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
    std::string test3 = "example.com";
    EXPECT_EQ(OBSPlugin::CheckIsValidIPv6(test1), false);
    EXPECT_EQ(OBSPlugin::CheckIsValidIPv6(test2), true);
    EXPECT_EQ(OBSPlugin::CheckIsValidIPv6(test3), false);
}

TEST_F(PluginUtilitiesTest, CheckIsValidIP)
{
    std::string test1 = "192.168.1.1";
    std::string test2 = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
    std::string test3 = "example.com";
    EXPECT_EQ(OBSPlugin::CheckIsValidIP(test1), true);
    EXPECT_EQ(OBSPlugin::CheckIsValidIP(test2), true);
    EXPECT_EQ(OBSPlugin::CheckIsValidIP(test3), false);
}

TEST_F(PluginUtilitiesTest, ParseDomain2IP)
{
    std::string test1 = "192.168.1.1";
    std::string test2 = "2001:0db8:85a3:0000:0000:8a2e:0370:7334";
    std::string test3 = "xxxxx.com";
    std::string result1 = OBSPlugin::ParseDomain2IP(test1);
    std::string result2 = OBSPlugin::ParseDomain2IP(test2);
    EXPECT_EQ(result1 == test1, true);
    EXPECT_EQ(result2 == test2, true);
    EXPECT_NO_THROW(OBSPlugin::ParseDomain2IP(test3));
}